/* ImageHandler.h
-----------------------------------------
By: 	Wei YE ( ye0003ei@e.ntu.edu.sg )

Date:	10/Oct/2012
-----------------------------------------
*/
#pragma once 

#include "MeanShift.h"
#include <cv.h>
#include <algorithm>
#include <list>
#include <vector>
using namespace std;

//data space conversion...
const double Xn			= 0.95050;
const double Yn			= 1.00000;
const double Zn			= 1.08870;

const double Un_prime	= 0.19784977571475;
const double Vn_prime	= 0.46834507665248;
const double Lt			= 0.008856;

const float  Dist_thresh = 0.1f;

//RGB to LUV conversion
const double XYZ[3][3] = {	{  0.4125,  0.3576,  0.1804 },
{  0.2125,  0.7154,  0.0721 },
{  0.0193,  0.1192,  0.9502 }	};

//LUV to RGB conversion
const double RGB[3][3] = {	{  3.2405, -1.5371, -0.4985 },
{ -0.9693,  1.8760,  0.0416 },
{  0.0556, -0.2040,  1.0573 }	};

enum ImageType{COLOR, GRAYSCALE};

struct Region {
	int			ID_;
	vector<int> ptInMode_;

	Region(int id){
		ID_ = id;
	}
};

typedef list<Region*> RegionList;

class ImageHandler
{
public:
	ImageHandler( int s, int r, int m)
	{
		SS_ = max(s, 1);
		SR_ = max(r, 1);
		M_  = max(m, 1);

		data_	  = NULL;
		uv_		  = NULL;
		labels_	  = NULL;
		idxTable_ = NULL;
	};

	~ImageHandler( void )
	{
		if( data_ )		delete []data_;
		if( uv_)		delete []uv_;
		if( labels_ )   delete []labels_;
		if( idxTable_ ) delete []idxTable_;

		for(RegionList::iterator itr = rList_.begin(); itr != rList_.end(); itr++)
			delete (*itr);
		rList_.clear();
	};   

	void LoadTheImage(cv::Mat& image, ImageType imagetype );

	void RGBtoLUV(cv::Vec3b* rgbVal, float* luvVal);

	void LUVtoRGB(float* luvVal, cv::Vec3b* rgbVal);

	void Segment();

	void Merge();

	void Fill(int pt, int label, float* msout);

	void Eliminate();

	int* GetLabel(){return labels_;};

private:

	MeanShift MS_;
	int SS_, SR_, M_; // sigma_s, sigma_r, M
	int H_, W_, D_;   // image height, width, channels+2

	float*  data_;	
	float*  uv_;

	int*    labels_;  // label for each data point
	int*    idxTable_;
	
	float*  modes_;    // modes list -- indexed by label 
	RegionList rList_;

	int     neigh[8];  // index look-up table for 8 connected neighbor 
};
